package com.rgbgame;

import org.jbox2d.testbed.ProcessingDebugDraw;

import com.rgbgame.about.AboutScene;
import com.rgbgame.intro.IntroScene;
import com.rgbgame.level.LevelScene;
import com.rgbgame.physics.Actor;
import com.rgbgame.ui.RGBConsole;

import processing.core.PApplet;

public class RGBApplet extends PApplet {
	private static final long serialVersionUID = 6125461035516653358L;
	
	/** Target frame rate */
	private int targetFPS = 600;
	/** Number of frames to average over when computing real FPS */
    private final int fpsAverageCount = 100; 
    /** Array of timings */
    private long[] nanos;
    /** When we started the nanotimer */
    private long nanoStart;
    /** Number of frames since we started. */
    private long frameCount = 0;
    /** Results go here */
    public float averagedFPS, totalFPS;
    
    /** The current game state */
    private GameState gameState = GameState.INTRO;
    
    /** Level game state handler */
    private LevelScene levelScene;
    /** About game state handler */
    private AboutScene aboutScene;
    /** Intro game state handler */
    private IntroScene introScene;
	
    /** The debug drawer passed to JBox2d for debugging */
	public ProcessingDebugDraw m_debugDraw;
	
	private RGBConsole console;
	
	private int bgColor;
	
	/**
	 * Called once on creation.
	 */
	public void setup() {
		/* Processing initialization */
		size(640,480,P3D);
    	frameRate(targetFPS);
    	
    	/* Reset all static variables */
    	resetStatics();
    	
    	m_debugDraw = new ProcessingDebugDraw(this);
    	
    	/* Request applet focus a bunch of times, hope we get it. */
    	for (int i=0; i<100; ++i) {
    		this.requestFocus();
    	}
    	
    	/* Set up the timers for FPS reporting */
    	initFrameTimer();
    	
    	introScene = new IntroScene();
    	aboutScene = new AboutScene();
    	levelScene = new LevelScene();
    	
    	bgColor = color(20.0f,20.0f,20.0f);
    	
    	console = new RGBConsole(this);
	}
	
	/**
	 * Called every frame.  Logic goes here.
	 */
	public void draw() {
		background(bgColor);
		
		/* Log FPS data */
		clickFrameTimer();
		
		if (keyPressed) console.println("Frame rate: "+averagedFPS);
		if (mousePressed) console.setVisible(true);
		else console.setVisible(false);
		
		/* Pass off control based on game state */
		switch(gameState) {
		case INTRO:
			setGameState(GameState.LEVELPLAY);
			break;
		case LEVELPLAY:
			break;
		case ABOUT:
			setGameState(GameState.LEVELPLAY);
			break;
		}
		
		/* Draw any debugging information to the screen */
		console.draw();
	}
		
	private void initFrameTimer() {
    	nanos = new long[fpsAverageCount];
    	long nanosPerFrameGuess = (long)(1000000000.0 / targetFPS);
    	nanos[fpsAverageCount-1] = System.nanoTime();
    	for (int i=fpsAverageCount-2; i>=0; --i) {
    		nanos[i] = nanos[i+1] - nanosPerFrameGuess;
    	}
    	nanoStart = System.nanoTime();
	}
	
	private void clickFrameTimer() {
		for (int i=0; i<fpsAverageCount-1; ++i) {
			nanos[i] = nanos[i+1];
		}
		nanos[fpsAverageCount-1] = System.nanoTime();
		averagedFPS = (float) ( (fpsAverageCount-1) * 1000000000.0 / (nanos[fpsAverageCount-1]-nanos[0]));
		++frameCount;
		totalFPS = (float) (frameCount * 1000000000 / (1.0*(System.nanoTime()-nanoStart)));
	}
	
	public GameState getGameState() {
		return gameState;
	}
	
	public void setGameState(GameState state) {
		gameState = state;
	}
	
	/** Static variables might not get reset on applet reload, do it manually. */
	public void resetStatics() {
		Actor.resetStatics();
		RGBInput.resetStatics();
	}
	
	/** Start PApplet as a Java program (can also be run as an applet). */
    static public void main(String args[]) {
        PApplet.main(new String[] { "com.rgbgame.RGBApplet" });
    }
}
